/*
 *        Author: Sidartha Carvalho <silobocarvalho@gmail.com>
 */

#include <stdio.h>
#include <../../usr/include/postgresql/libpq-fe.h> //To define local header.
#include <time.h>
#include <limits.h>
/*
 * To compile: gcc -o name -I /usr/include/postgresql/ name.c -lpq
 * change: /usr/include/postgresql/ to your postgresql path.
 */

PGconn *conn = NULL;
PGresult *result;
int bdOpen = 0;


static int MSGSHORTLENGTH = 16;
static int MSGLONGLENGTH = 30;
static int MSGSHORTLENGTHNEGATIVE = -16;
static int MSGLONGLENGTHNEGATIVE = -30;

void hex2bin(char *hex, char* dest);
int adicionarAoBd(char* querySql);
int abrirConexaoBD();



int main(void) {
    FILE *ifp;
    char *mode = "r";
    char inputFilename[] = "test";
    char msg[31];
    char oldValueShort[18];
    char oldValueLong[31];
    char tempValue[31];
    char icaoAddress[7];
    char lat[18], lng[18], alt[13];// A lat e lng são 17 bits, +1 para '\0'. Altitude é 12 bits.
    char msgBin[113];
    char msgToConvert[31];

    int score, i, countFile = 0, k;
    int test, msgLenght;
    char* query = malloc(sizeof(char) * 500);
    time_t t;
    time(&t);
    ifp = fopen(inputFilename, mode);

    if (ifp == NULL) {
        fprintf(stderr, "Can't open input file !\n");
        return 1;
    }

//Message Model: @ + 14Bytes + ; or @ + 28Bytes + ;

//First part, when the file is read first time.

    while (EOF != (i = fscanf(ifp, "%s", msg))) {

        msgLenght = strlen(msg);
        if (msgLenght == MSGSHORTLENGTH) {
            printf("%s", "Msg Curta \n");
            printf("%s\n", msg);
            if(bdOpen == 0){
            abrirConexaoBD();
            bdOpen=1;
			}
			/*Two first bytes define the message type.
			 * 8D - Position Message
			 * XX - Identity Message
			 * XX - Velocity Message
			 * */

        } else if (msgLenght == MSGLONGLENGTH) {
            printf("%s", "Msg Longa \n");
            if(msg[1] == '8' && msg[2] == 'D') //Position Message
			 {
				 printf("É uma mensagem de Posição\n");
				 strcpy(icaoAddress, ""); //Clean
				 for(k=0; k<6; k++) //ICAO 6 bytes
					{
					 icaoAddress[k] = msg[k+3];
					}
				 strcpy(msgToConvert, &msg[1]);

				 msgToConvert[28] = '\0'; //  28 because the vector have 30 elements,  [0] is @ and the last is ;

				 printf("%s\n", msgToConvert);

				 strcpy(msgBin, "");//Clean

				 hex2bin(msgToConvert,msgBin); //Convert Hex message to Bin, to extract the values

				 printf("\n\n%s\n", msgBin);

				  // [32] Begin information. 6 bytes of ICAO and 2 bytes of message type
				  // [40] Begin Altitude + 12 to end
				  strcpy(alt, "");//Clean
				  for(k=0; k<12; k++)
					  {
					  alt[k] = msgBin[k+40];
					  }
				  alt[12] = '\0'; //Close String


				  for(k=0; k<17; k++)
				      {
					  lat[k] = msgBin[k+54];
					  }
				  lat[17] = '\0';

			      for(k=0; k<17; k++)
				  {
					  lng[k] = msgBin[k+71];
					  }
					  lng[17] = '\0';



				 strcpy(query, "");

				  time(&t);
				 strcpy(query, "INSERT INTO current_flights (voo, altitude, latitude, longitude, voots, posicaots) VALUES ('");
				 strcat(query, icaoAddress);
				 strcat(query,"' , '");
				 strcat(query, alt);
				 strcat(query,"' , '");
				 strcat(query, lat);
				 strcat(query,"' , '");
				 strcat(query, lng);
				 strcat(query,"' , '");
				 strcat(query, ctime(&t));
				 strcat(query,"' , '");
				 strcat(query, ctime(&t));
				 strcat(query,"')");
				 printf("\n%s\n", query);
				 adicionarAoBd(query); //Lat, Lng and Alt were saved in bits
			 }
			    else if(msg[1] == '5' && msg[2] == 'D')
             {
				 printf("É uma mensagem de Voo\n");
				//To do, I don't know how decode the Identity message

/*
				 time(&t); //To get current time
				 strcpy(query, "INSERT INTO current_flights (voo, voots) VALUES ('");
				 strcat(query, msg);
				 strcat(query,"' , '");
				 strcat(query, ctime(&t));
				 strcat(query,"')");
				 adicionarAoBd(query);
				 * */

			 }
			 else if(msg[1] == '5' && msg[2] == 'B')
			 {
				 printf("É uma mensagem de Velocidade\n");
				 //To do, I don't know how decode the velocity message
            	 /*
            	 time(&t);
				 strcpy(query, "INSERT INTO current_flights (voo, voots) VALUES ('");
				 strcat(query, msg);
				 strcat(query,"' , '");
				 strcat(query, ctime(&t));
				 strcat(query,"')");
				 adicionarAoBd(query);
				 * */
			 }
        }
    }

	fclose(ifp);


//Second Part, when new information is added to the file.
printf("\n INICIO SEGUNDA PARTE \n");
    do {
        ifp = fopen("test", mode);
        fseek(ifp, -18, SEEK_END);
        fscanf(ifp, "%s", msg);
		printf("Username: %s and username[0] = %c\n", msg, msg[0]);

        if(msg[0] != '@') /*Rewind the cursor, if the first byte is @, is the begin of message and is a short message because I rewind 18 bytes.*/
        {
		fseek(ifp, MSGLONGLENGTHNEGATIVE -2, SEEK_END);/*The long message plus EOF plus '\0' */
        fscanf(ifp, "%s", msg);



        oldValueLong[29] = '\0';
        msg[29] = '\0';

        if(strcmp(oldValueLong, msg) == 0){
//If equals, do anything.

			}else{


            printf("\n\nOld Value: %s \n Msg: %s\n\n", oldValueLong, msg);



            strcpy(oldValueLong, msg);

                   if(msg[1] == '8' && msg[2] == 'D') //Position Message
			 {
				 printf("É uma mensagem de Posição\n");
				 strcpy(icaoAddress, ""); //Clean
				 for(k=0; k<6; k++) //ICAO 6 bytes
					{
					 icaoAddress[k] = msg[k+3];
					}
				 strcpy(msgToConvert, &msg[1]);

				 msgToConvert[28] = '\0'; //  28 because the vector have 30 elements,  [0] is @ and the last is ;

				 printf("%s\n", msgToConvert);

				 strcpy(msgBin, "");//Clean

				 hex2bin(msgToConvert,msgBin); //Convert Hex message to Bin, to extract the values

				 printf("\n\n%s\n", msgBin);

				  // [32] Begin information. 6 bytes of ICAO and 2 bytes of message type
				  // [40] Begin Altitude + 12 to end
				  strcpy(alt, "");//Clean
				  for(k=0; k<12; k++)
					  {
					  alt[k] = msgBin[k+40];
					  }
				  alt[12] = '\0'; //Close String


				  for(k=0; k<17; k++)
				      {
					  lat[k] = msgBin[k+54];
					  }
				  lat[17] = '\0';

			      for(k=0; k<17; k++)
				  {
					  lng[k] = msgBin[k+71];
					  }
					  lng[17] = '\0';



				 strcpy(query, "");

				  time(&t);
				 strcpy(query, "INSERT INTO current_flights (voo, altitude, latitude, longitude, voots, posicaots) VALUES ('");
				 strcat(query, icaoAddress);
				 strcat(query,"' , '");
				 strcat(query, alt);
				 strcat(query,"' , '");
				 strcat(query, lat);
				 strcat(query,"' , '");
				 strcat(query, lng);
				 strcat(query,"' , '");
				 strcat(query, ctime(&t));
				 strcat(query,"' , '");
				 strcat(query, ctime(&t));
				 strcat(query,"')");
				 printf("\nQuery: %s\n", query);
				 adicionarAoBd(query); //Lat, Lng and Alt were saved in bits
			 }
			    else if(msg[1] == '5' && msg[2] == 'D')
             {
				 printf("É uma mensagem de Voo\n");
				//To do, I don't know how decode the Identity message

/*
				 time(&t); //To get current time
				 strcpy(query, "INSERT INTO current_flights (voo, voots) VALUES ('");
				 strcat(query, msg);
				 strcat(query,"' , '");
				 strcat(query, ctime(&t));
				 strcat(query,"')");
				 adicionarAoBd(query);
				 * */

			 }
			 else if(msg[1] == '5' && msg[2] == 'B')
			 {
				 printf("É uma mensagem de Velocidade\n");
				 //To do, I don't know how decode the velocity message
            	 /*
            	 time(&t);
				 strcpy(query, "INSERT INTO current_flights (voo, voots) VALUES ('");
				 strcat(query, msg);
				 strcat(query,"' , '");
				 strcat(query, ctime(&t));
				 strcat(query,"')");
				 adicionarAoBd(query);
				 * */
			 }
  }
        }
        else //Is a short message
			{
			printf("A MENSAGEM É Short\n");
            fseek(ifp, MSGSHORTLENGTHNEGATIVE -2, SEEK_END);
            if(strcmp(oldValueShort, msg) == 0){

			}else{
            strcpy(oldValueShort, msg);

            strcpy(query, "INSERT INTO current_flights (voo) VALUES ('");
            strcat(query, msg);
            strcat(query,"')");
            adicionarAoBd(query);
			}
			}
		fclose(ifp);
        sleep(1);
    } while (1);
    fclose(ifp);
    return 0;
}

void hex2bin(char *hex, char* dest)
{
		 int i;
		 for(i=0;hex[i]!='\0';i++)
		 {
		  switch(hex[i])
		   {
		    case '0':
		     strcat(dest, "0000");
		     break;
		    case '1':
		     strcat(dest, "0001");
		     break;
		    case '2':
		     strcat(dest, "0010");
		     break;
		    case '3':
		     strcat(dest, "0011");
		     break;
		    case '4':
		     strcat(dest, "0100");
		     break;
		    case '5':
		     strcat(dest, "0101");
		     break;
		    case '6':
		     strcat(dest, "0110");
		     break;
		    case '7':
		     strcat(dest, "0111");
		     break;
		    case '8':
		     strcat(dest, "1000");
		     break;
		    case '9':
		     strcat(dest, "1001");
		     break;
		    case 'a':
		    case 'A':
		     strcat(dest, "1010");
		     break;
		    case 'b':
		    case 'B':
		     strcat(dest, "1011");
		     break;
		    case 'c':
		    case 'C':
		     strcat(dest, "1100");
		     break;
		    case 'd':
		    case 'D':
		     strcat(dest, "1101");
		     break;
		    case 'e':
		    case 'E':
		     strcat(dest, "1110");
		     break;
		    case 'f':
		    case 'F':
		     strcat(dest, "1111");
		     break;
		    default:
		     printf("Entered number is not Hexadecimal.Printed value is notcorrect.");
		     break;
		   }
		  }
}

int abrirConexaoBD(){

    /*realiza a conexão*/
    conn = PQconnectdb("host=localhost dbname=adsb user=postgres password=postgres");

    if(PQstatus(conn) == CONNECTION_OK)
    {
        printf("Conexão com efetuada com sucesso. \n");
    }
    else
    {
        printf("Falha na conexão. Erro: %s", PQerrorMessage(conn));
        PQfinish(conn);
        return -1;
    }

    return 0;
}

int adicionarAoBd(char* querySql)
{
//"INSERT INTO current_flights (voo) VALUES ('voo 1')"
    printf("\nQuery: %s\n", querySql);
    result = PQexec(conn, querySql);

    if(!result)
    {
        printf("Erro executando comando. ");
    }
    else
    {
        switch(PQresultStatus(result))
        {
            case PGRES_EMPTY_QUERY:
                printf("Nada aconteceu. ");
                break;
            case PGRES_FATAL_ERROR:
                printf("Error in query: %s ", PQresultErrorMessage(result));
                break;
            case PGRES_COMMAND_OK:
                printf("%s linhas afetadas. ", PQcmdTuples(result));
                break;
            default:
                printf("Algum outro resultado ocorreu. ");
                break;
        }

        /*Libera o nosso objeto*/

        PQclear(result);

    }
}
